﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace lab2
{
    public partial class Form1 : Form
    {
        private List<string> operators = new List<string>(new string[] { "(", ")", "+", "-", "*", "/"});

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            listBox2.Items.Clear();
            string input = textBox1.Text;
            string[] RPN = ConvertToRPN(input);
            string[] AssemblerCode = ConvertRPNToAssembler(RPN);
            for (int i = 0; i < AssemblerCode.Length; i++)
            {
                listBox2.Items.Add(AssemblerCode[i]);
            }
        }

        public string[] ConvertToRPN(string input)
        {
            List<string> outputSeparated = new List<string>();
            Stack<string> stack = new Stack<string>();
            List<string> inputSeparated = Separate(input);
            string c;
            for(int i=0;i<inputSeparated.Count;i++){
                c = inputSeparated[i];
                if (operators.Contains(c))
                {
                    if (stack.Count > 0 && !c.Equals("("))
                    {
                        if (c.Equals(")"))
                        {
                            string s = stack.Pop();
                            while (s != "(")
                            {
                                outputSeparated.Add(s);
                                s = stack.Pop();
                            }
                        }
                        else if(c.Equals("-") && inputSeparated[i-1].Equals("("))
                        {
                            stack.Push("--");
                        }
                        else if (GetPriority(c) >= GetPriority(stack.Peek()))
                            stack.Push(c);
                        else
                        {
                            while (stack.Count > 0 && GetPriority(c) < GetPriority(stack.Peek()))
                                outputSeparated.Add(stack.Pop());
                            stack.Push(c);
                        }
                    }
                    else
                    {
                        if (c.Equals("-") && (i==0 || inputSeparated[i-1].Equals("=")))
                        {
                            stack.Push("--");
                        }
                        else
                        {
                            stack.Push(c);
                        }
                    }
                }
                else if (!c.Equals(" "))
                {
                    outputSeparated.Add(c);
                    if (stack.Count > 0 && stack.Peek().Equals("-") &&inputSeparated.Count>(i+1) && inputSeparated[i+1].Equals("-"))
                    {
                        outputSeparated.Add(stack.Pop());
                    }
                }
                else
                {
                    inputSeparated.RemoveAt(i);
                    i--;
                }

            }
            if (stack.Count > 0)
                foreach (string d in stack)
                    outputSeparated.Add(d);

            return outputSeparated.ToArray();
        }

        private byte GetPriority(string s)
        {
            switch (s)
            {
                case "(":
                    return 0;
                case ")":
                    return 1;
                case "+":
                case "-":
                    return 2;
                case "/":
                    return 3;
                case ",*":
                    return 3;
                default:
                    return 4;
            }
        }

        private List<string> Separate(string input) 
        {
            List<string> output = new List<string>();
            int pos = 0;
            while (pos < input.Length)
            {
                string s = string.Empty + input[pos];
                if (!operators.Contains(input[pos].ToString()))
                {
                    if (Char.IsDigit(input[pos]))
                        for (int i = pos + 1; i < input.Length &&
                            (Char.IsDigit(input[i]) || input[i] == ',' || input[i] == '.'); i++)
                            s += input[i];
                    else if (Char.IsLetter(input[pos]))
                        for (int i = pos + 1; i < input.Length &&
                            (Char.IsLetter(input[i]) || Char.IsDigit(input[i])); i++)
                            s += input[i];
                }
                output.Add(s);
                pos += s.Length;
            }
            return output;
        }

        private string[] ConvertRPNToAssembler(string[] input)
        {
            List<string> output = new List<string>();
            List<string> inputList = input.ToList();
            int i = 0;		
            List<string> allOperators = new List<string>(operators);
            allOperators.Add("--");
            while (i < inputList.Count)
            {
                if (allOperators.Contains(inputList[i]))
                {
                    if(!inputList[i].Equals("--"))
					{
                            if (!inputList[i - 2].Equals("ax"))
                            {
                                if (inputList[i - 2].Equals("pop"))
                                {
                                    output.Add("mov bx," + inputList[i - 1]);
                                    output.Add("pop ax");
                                }
                                else
                                {
                                    output.Add("mov bx," + inputList[i - 1]);
                                    output.Add("mov ax," + inputList[i - 2]);
                                }
                            }
                            else
                            {
                                output.Add("mov bx," + inputList[i - 1]);
                            }

							if(inputList[i].Equals("+"))
							{
                                output.Add("add ax,bx");
						    }
							else if (inputList[i].Equals("*"))
							{
                                output.Add("mul ax,bx");
						    }
							else if (inputList[i].Equals("-"))
							{
                                output.Add("sub ax,bx");
						    }
							else
							{
                                output.Add("div ax,bx");
						    }

                            if ((i+2)<inputList.Count && !operators.Contains(inputList[i + 1]) && !operators.Contains(inputList[i + 2]))
                            {
                                output.Add("push ax");
                                inputList[i] = "pop";
                            }
                            else
                            {
                                inputList[i] = "ax";
                            }
                            inputList.RemoveAt(i - 1);
                            inputList.RemoveAt(i - 2);
                            i = i-2;
                    }
					else 
					{
                                if (!inputList[i - 1].Equals("ax"))
                                {
                                    if(!inputList[i-1].Equals("pop"))
                                    {
                                        output.Add("mov ax," + inputList[i - 1]);
                                    }
                                    else
                                    {
                                        output.Add("pop ax");
                                    }
                                }
                                output.Add("neg ax");
                                output.Add("push ax");
                                inputList[i] = "pop";
                                inputList.RemoveAt(i - 1);
                                i = i-1;
                    }
                }
                i = i + 1;
            }
            if (inputList.Count>1 && inputList[1].Equals("="))
            {
                output.Add("mov " + inputList[0] + ", ax");
            }
            return output.ToArray();
        }

        private void listBox2_SelectedIndexChanged(object sender, EventArgs e)
        {

        }
    }
}
